//package com.yc.springmvc;
//
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.yc.springmvc.web.DemoController;
//import jakarta.servlet.RequestDispatcher;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.ServletInputStream;
//import jakarta.servlet.http.HttpServlet;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import jakarta.servlet.http.HttpSession;
//import org.springframework.context.ApplicationContext;
//import org.springframework.stereotype.Controller;
//import org.springframework.web.bind.annotation.*;
//import org.springframework.web.servlet.ModelAndView;
//
//import java.io.*;
//import java.lang.annotation.Annotation;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.lang.reflect.Parameter;
//import java.nio.charset.Charset;
//import java.nio.charset.StandardCharsets;
//import java.util.*;
//
//public class MyDispatcherServlet extends HttpServlet {
//
//    protected ApplicationContext applicationContext;
//    protected Set<Object> controllers = new HashSet<>();
//    protected Map<String, Handler> handlers = new HashMap<>();
//
//    public MyDispatcherServlet(ApplicationContext applicationContext) {
//        this.applicationContext = applicationContext;
//        // 查找所有的控制器
//        Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(Controller.class);
//        Map<String, Object> restControllers = applicationContext.getBeansWithAnnotation(RestController.class);
//        this.controllers.addAll(controllers.values());
//        this.controllers.addAll(restControllers.values());
////        this.controllers.forEach(System.out::println);
//
//        // 构建地址与Handler的关系
//        this.controllers.forEach(controller -> {
//            // 类上地址
//            String classAddr = "";
//            if (controller.getClass().isAnnotationPresent(RequestMapping.class)) {
//                classAddr = getAddress(controller.getClass().getAnnotation(RequestMapping.class));
//            }
//            for (Method method : controller.getClass().getDeclaredMethods()) {
//                if (method.isAnnotationPresent(RequestMapping.class) ||
//                        method.isAnnotationPresent(GetMapping.class) ||
//                        method.isAnnotationPresent(PostMapping.class)) {
//                    // 控制器方法
//                    Annotation annotation = method.getAnnotation(RequestMapping.class);
//                    if (annotation == null) {
//                        annotation = method.getAnnotation(GetMapping.class);
//                        if (annotation == null) {
//                            annotation = method.getAnnotation(PostMapping.class);
//                        }
//                    }
//                    // 提取方法地址
//                    String methodAddr = getAddress(annotation);
//                    // 完整地址
//                    String fullAddr = (classAddr.isEmpty() == false ? classAddr + "/" : "") + methodAddr;
//                    // 构建handler对象
//                    Handler handler = new Handler(controller, method);
//                    if (fullAddr.startsWith("/") == false) {
//                        fullAddr = "/" + fullAddr;
//                    }
//                    // 加入集合
//                    handlers.put(fullAddr, handler);
//                }
//            }
//        });
//
//        this.handlers.forEach((k, v) -> {
//            System.out.println(k + ": " + v);
//        });
//    }
//
//    private String getAddress(Annotation annotation) {
//        // 提取地址
//        try {
//            Method value = annotation.getClass().getDeclaredMethod("value");
//            Method path = annotation.getClass().getDeclaredMethod("path");
//            String[] values = (String[]) value.invoke(annotation);
//            if (values.length == 0) {
//                values = (String[]) path.invoke(annotation);
//            }
//            return values[0];
//        } catch (Exception e) {
//            throw new RuntimeException("获取地址失败!", e);
//        }
//
//    }
//
//    @Override
//    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        try {
//            req.setCharacterEncoding("GBK");
//        } catch (UnsupportedEncodingException e) {
//            throw new RuntimeException(e);
//        }
//        // 查找 handler
//        Handler handler = getHandler(req);
//        System.out.println("handler = " + handler);
//
//        ModelAndView mv = null;
//
//        if (handler == null) {
//            // TODO 静态资源 or 404
//            resp.setContentType("text/html;charset=utf-8");
//            resp.getWriter().print("TODO 静态资源 or 404: " + req.getRequestURI());
//            return;
//            // TODO 静态资源通过读文件返回文件内容
//        } else {
//            // 执行 handler, 获取 ModelAndView
//            mv = handler.handle(req, resp);
//        }
//
//        // 处理结果 ModelAndView
//        render(mv, req, resp);
//    }
//
//    // 渲染视图
//    private void render(ModelAndView mv, HttpServletRequest req, HttpServletResponse resp) {
//        if (mv.getViewName() == null || mv.isEmpty()) {
//            // 返回json
//            Object data = mv.getModel().get("JSON");
//            ObjectMapper objectMapper = new ObjectMapper();
//            try {
//                String json = objectMapper.writeValueAsString(data);
//                resp.setContentType("application/json;charset=utf-8");
//                resp.getWriter().print(json);
//            } catch (JsonProcessingException e) {
//                throw new RuntimeException("转JSON失败!",e);
//            } catch (IOException e) {
//                throw new RuntimeException("输出至浏览器失败",e);
//            }
//        } else {
//            // 跳转页面
//            String viewName = mv.getViewName();
//            if(viewName.startsWith("redirect:")){
//                // 响应重定向
//                String location = viewName.substring("redirect:".length());
//                try {
//                    resp.sendRedirect(location);
//                } catch (IOException e) {
//                    throw new RuntimeException("响应重定向失败!", e);
//                }
//            } else {
//                // 请求转发
//                String path = viewName;
//                if(viewName.startsWith("forward:")){
//                    path = viewName.substring("forward:".length());
//                }
//                RequestDispatcher dispatcher = req.getRequestDispatcher(path);
//                try {
//                    dispatcher.forward(req,resp);
//                } catch (Exception e) {
//                    throw new RuntimeException("请求转发错误",e);
//                }
//            }
//        }
//
//    }
//
//    // 获取 Handler
//    Handler getHandler(HttpServletRequest req) {
//        System.out.println("req.getServletPath() = " + req.getServletPath());
//        return handlers.get(req.getServletPath());
//    }
//
//}
//
//class Handler {
//    Object controller;
//    Method method;
//
//    public Handler(Object controller, Method method) {
//        this.controller = controller;
//        this.method = method;
//    }
//
//    ModelAndView handle(HttpServletRequest request, HttpServletResponse response) {
//        // request.setCharacterEncoding => 设置请求体(body)的字符集编码
//        try{
//            method.setAccessible(true);
//            Object ret = null;
//            if (method.getParameterCount() == 0) {
//                // 调用无参数的方法
//                ret = method.invoke(controller);
//            } else {
//                // 有参数调用
//                // 创建参数列表
//                List<Object> params = new ArrayList<>();
//                // 注入参数值
//                for (int i = 0; i < method.getParameterTypes().length; i++) {
//                    Class<?> type = method.getParameterTypes()[i];
//                    // 简单参数 + Servlet对象
//                    if(type.isAssignableFrom(HttpServletRequest.class)){
//                        params.add(request);
//                    } else if(type.isAssignableFrom(HttpServletResponse.class)){
//                        params.add(response);
//                    } else if(type.isAssignableFrom(HttpSession.class)){
//                        params.add(request.getSession());
//                    } else if(type.isAssignableFrom(InputStream.class)){
//                        params.add(request.getInputStream());
//                    } else if(type.isAssignableFrom(OutputStream.class)){
//                        params.add(response.getOutputStream());
//                    } else if(type.isAssignableFrom(ModelAndView.class)){
//                        params.add(new ModelAndView());
//                    } else if(type.isAssignableFrom(String.class)
//                            || type.isAssignableFrom(Integer.class)
//                            || type.isAssignableFrom(Long.class)
//                            || type.isPrimitive()){
//                        // isPrimitive 判断是否是原始数据类型
//                        // 获取参数名
//                        Parameter parameter = method.getParameters()[i];
//                        RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
//                        String name = requestParam.value();
//                        String defalutValue = requestParam.defaultValue();
//                        // 从请其中获取参数值
//                        String value = request.getParameter(name);
//                        if(value == null){
//                            value = defalutValue;
//                        }
//                        if (type.isAssignableFrom(String.class)) {
//                            // TODO 判断参数上是否有 RequestHeader, CookieValue, PathVariable 注解
//                            // TODO 直接从对应位置提取参数
//                            params.add(value);
//                        } else if (type.isAssignableFrom(Integer.class)
//                                ||type.isAssignableFrom(int.class)) {
//                            params.add(Integer.parseInt(value));
//                        } else if (type.isAssignableFrom(Long.class)){
//                            params.add(Long.parseLong(value));
//                        } else {
//                            // TODO 其他基本数据类型请自行扩展
//                        }
//                    } else {
//                        // 实体对象参数
//                        // User user => request.  name, age, father.name, mather.age
//                        Object object = null; // new User()
//                        if(method.getParameters()[i].getAnnotation(RequestBody.class) != null){
//                            // json 格式 请求体
//                            ServletInputStream in = request.getInputStream();
//                            // 因为是自定义读取body, 编码不能使用官方API, 需要自己处理编码问题
//                            InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
//                            char[] cbuf = new char[1024];
//                            int len = isr.read(cbuf);
//                            String json = new  String(cbuf, 0, len);
//                            ObjectMapper objectMapper = new ObjectMapper();
//                            object = objectMapper.readValue(json, type);
//                        } else {
//                            object = type.newInstance(); // new User()
//                            // 从请求中提取参数值设置到对应属性中
//                            Enumeration<String> names = request.getParameterNames();
//                            // 遍历所有的请求参数
//                            while(names.hasMoreElements()){
//                                String fieldName = names.nextElement();
//                                String filedValue = request.getParameter(fieldName);
//                                setValue(object, fieldName, filedValue);
//                            }
//                        }
//                        params.add(object);
//                    }
//                }
//                // 调用方法
//                System.out.println("params = " + params);
//                ret = method.invoke(controller, params.toArray());
//            }
//
//            if(ret instanceof ModelAndView) {
//                // ret 如果是 ModelAndView 直接返回,
//                return (ModelAndView)ret;
//            }
//            if(controller.getClass().isAnnotationPresent(RestController.class)) {
//                // 否则 创建ModelAndView, 将ret放入ModelAndView中返回
//                ModelAndView mv = new ModelAndView();
//                mv.addObject("JSON",ret);
//                return mv;
//            } else if(controller.getClass().isAnnotationPresent(Controller.class)) {
//                // 如果当前控制器是 Controller,
//                // 如果方法上有 ResponseBody 注解, 则转 json
//                if (method.isAnnotationPresent(ResponseBody.class)) {
//                    ModelAndView mv = new ModelAndView();
//                    mv.addObject("JSON",ret);
//                    return mv;
//                } else {
//                    // 否则转为字符串, 则跳转至指定页面
//                    String viewName = ret.toString();
//                    ModelAndView mv = new ModelAndView();
//                    mv.setViewName(viewName);
//                    return mv;
//                }
//            }
//        } catch (Exception e){
//            throw new RuntimeException("执行控制器方法错误!",e);
//        }
//        return null;
//    }
//
//    private void setValue(Object object, String fieldName, String filedValue) {
//        try{
//            if(fieldName.contains(".")){
//                //递归调用设置属性对象的内部属性值
//                String prefix = fieldName.substring(0, fieldName.indexOf("."));
//                String suffix = fieldName.substring(fieldName.indexOf(".") + 1);
//                Field field = object.getClass().getDeclaredField(prefix);
//                field.setAccessible(true);
//                Object fieldObject = field.getType().newInstance();
//                field.set(object,fieldObject);  // user.setFather(fieldObject);
//                setValue(fieldObject,suffix,filedValue);
//            } else {
//                Field field = object.getClass().getDeclaredField(fieldName);
//                field.setAccessible(true);
//                if(field.getType().isAssignableFrom(String.class)){
//                    field.set(object, filedValue);
//                } else if (field.getType().isAssignableFrom(Integer.class)
//                        || field.getType().isAssignableFrom(int.class)){
//                    field.set(object, Integer.parseInt(filedValue));
//                } else if (field.getType().isAssignableFrom(Boolean.class)
//                        || field.getType().isAssignableFrom(boolean.class)){
//                    field.set(object, Boolean.parseBoolean(filedValue));
//                }
//                // TODO 其他类型请自行扩展
//            }
//        }catch( Exception e){
//            throw new RuntimeException("设置对象属性值错误", e);
//        }
//    }
//
//    @Override
//    public String toString() {
//        return "Handler{" +
//                "controller=" + controller +
//                ", method=" + method +
//                '}';
//    }
//}
